September 2013 invalidation client release - Add support for OAuth2 to Android network channel git-svn-id: http://google-cache-invalidation-api.googlecode.com/svn/trunk@313 1cc9d426-c294-39be-ba72-c0199ca0f247
diff --git a/src/java/com/google/ipc/invalidation/common/BuildConstants.java b/src/java/com/google/ipc/invalidation/common/BuildConstants.java index 8e65cf3..ab87af2 100644 --- a/src/java/com/google/ipc/invalidation/common/BuildConstants.java +++ b/src/java/com/google/ipc/invalidation/common/BuildConstants.java
@@ -33,5 +33,5 @@ /** Build constant definitions. */ class BuildConstants { - static final int BUILD_DATESTAMP = 20130807; + static final int BUILD_DATESTAMP = 20130902; } diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java index bb5aad3..f5fe9ff 100644 --- a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java +++ b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java
@@ -54,7 +54,13 @@ public static final String EXTRA_AUTH_TOKEN = "com.google.ipc.invalidation.AUTH_TOKEN"; - /** Extra in the intent from the application that provides the auth token type. */ + /** + * Extra in the intent from the application that provides the so-called "auth token type". If + * the auth token is a GoogleLogin token, then this value must name the Gaia service (e.g., + * "chromiumsync") for which the token was generated. If the auth token is a Gaia OAuth2 token, + * then this value must have the form "oauth2:{scope}", where {scope} is a Google API + * authentication scope such as "https://www.googleapis.com/auth/chromesync". + */ public static final String EXTRA_AUTH_TOKEN_TYPE = "com.google.ipc.invalidation.AUTH_TOKEN_TYPE"; diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java index f9e340f..2d7ec6f 100644 --- a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java +++ b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java
@@ -59,6 +59,11 @@ /* This class is public so that it can be instantiated by the Android runtime. */ /** + * A prefix on the "auth token type" that indicates we're using an OAuth2 token to authenticate. + */ + private static final String OAUTH2_TOKEN_TYPE_PREFIX = "oauth2:"; + + /** * Client key used in network endpoint ids. We only have one client at present, so there is no * need for a key. */ @@ -224,8 +229,9 @@ HttpURLConnection urlConnection = null; try { // Open the connection. - url = buildUrl(authTokenType, networkEndpointId); - urlConnection = createUrlConnectionForPost(this, url, authToken); + boolean isOAuth2Token = authTokenType.startsWith(OAUTH2_TOKEN_TYPE_PREFIX); + url = buildUrl(isOAuth2Token ? null : authTokenType, networkEndpointId); + urlConnection = createUrlConnectionForPost(this, url, authToken, isOAuth2Token); urlConnection.setFixedLengthStreamingMode(outgoingMessage.length); urlConnection.connect(); @@ -283,10 +289,11 @@ /** * Returns a URL to use to send a message to the data center. * - * @param authTokenType type of authentication token that will be used in the request + * @param gaiaServiceId Gaia service for which the request will be authenticated (when using a + * GoogleLogin token), or {@code null} when using an OAuth2 token. * @param networkEndpointId network id of the client */ - private static URL buildUrl(String authTokenType, NetworkEndpointId networkEndpointId) + private static URL buildUrl(String gaiaServiceId, NetworkEndpointId networkEndpointId) throws MalformedURLException { StringBuilder urlBuilder = new StringBuilder(); @@ -294,13 +301,20 @@ // id. urlBuilder.append((channelUrlForTest != null) ? channelUrlForTest : HttpConstants.CHANNEL_URL); urlBuilder.append(HttpConstants.REQUEST_URL); + + // TODO: We should be sending a ClientGatewayMessage in the request body + // instead of appending the client's network endpoint id to the request URL. Once we do that, we + // should use a UriBuilder to build up a structured Uri object instead of the brittle string + // concatenation we're doing below. urlBuilder.append(base64Encode(networkEndpointId.toByteArray())); // Add query parameter indicating the service to authenticate against - urlBuilder.append('?'); - urlBuilder.append(HttpConstants.SERVICE_PARAMETER); - urlBuilder.append('='); - urlBuilder.append(authTokenType); + if (gaiaServiceId != null) { + urlBuilder.append('?'); + urlBuilder.append(HttpConstants.SERVICE_PARAMETER); + urlBuilder.append('='); + urlBuilder.append(gaiaServiceId); + } return new URL(urlBuilder.toString()); } @@ -312,10 +326,11 @@ * @param context Android context * @param url URL to which to post * @param authToken auth token to provide in the request header + * @param isOAuth2Token whether the token is an OAuth2 token (vs. a GoogleLogin token) */ public static HttpURLConnection createUrlConnectionForPost(Context context, URL url, - String authToken) throws IOException { + String authToken, boolean isOAuth2Token) throws IOException { HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try { connection.setRequestMethod("POST"); @@ -323,7 +338,11 @@ throw new RuntimeException("Cannot set request method to POST: " + exception); } connection.setDoOutput(true); - connection.setRequestProperty("Authorization", "GoogleLogin auth=" + authToken); + if (isOAuth2Token) { + connection.setRequestProperty("Authorization", "Bearer " + authToken); + } else { + connection.setRequestProperty("Authorization", "GoogleLogin auth=" + authToken); + } connection.setRequestProperty("Content-Type", HttpConstants.PROTO_CONTENT_TYPE); connection.setRequestProperty("User-Agent", context.getApplicationInfo().className + "(" + Build.VERSION.RELEASE + ")");